/*
 * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
 * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
 * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
 * Vestibulum commodo. Ut rhoncus gravida arcu.
 */

package com.mrd.gtimpframe.service.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.PageInfo;
import com.mrd.base.Jqgrid;
import com.mrd.framework.config.web.json.Result;
import com.mrd.framework.ui.filter.SearchRule;
import com.mrd.framework.ui.filter.SearchRuleOption;
import com.mrd.framework.utils.HttpUtils;
import com.mrd.freemarker.FreemarkerHandler;
import com.mrd.gtimp.base.entity.Company;
import com.mrd.gtimp.base.entity.User;
import com.mrd.gtimp.base.service.UserBiz;
import com.mrd.gtimp.business.entity.Declaration;
import com.mrd.gtimp.business.entity.DeclarationFree;
import com.mrd.gtimp.business.service.DeclarationFreeBiz;
import com.mrd.gtimpframe.entity.DeclaCheckContent;
import com.mrd.gtimpframe.entity.DeclaCheckTracking;
import com.mrd.gtimpframe.entity.DeclaDocHanOutRecord;
import com.mrd.gtimpframe.entity.DeclaOperationRecord;
import com.mrd.gtimpframe.entity.Dictionary;
import com.mrd.gtimpframe.entity.OperationStatistics;
import com.mrd.gtimpframe.entity.OperationalEfficiency;
import com.mrd.gtimpframe.entity.RejectRecord;
import com.mrd.gtimpframe.repository.DeclaCheckContentMapper;
import com.mrd.gtimpframe.repository.DeclaCheckCtDeptRefMapper;
import com.mrd.gtimpframe.repository.DeclaCheckTrackingMapper;
import com.mrd.gtimpframe.repository.DeclaDocHanOutRecordMapper;
import com.mrd.gtimpframe.repository.DeclaOperationRecordMapper;
import com.mrd.gtimpframe.repository.DeclarationMapper;
import com.mrd.gtimpframe.service.DeclaOperationRecordService;
import com.mrd.gtimpframe.service.DictionaryService;
import com.mrd.gtimpframe.vo.DeclaOperationRecordVO;
import com.mrd.util.JsonBinder;
import com.mrd.util.LoginUtil;
import com.mrd.util.ResponseUtils;
import com.mrd.util.StringUtils;

import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by dengdc on 2017/11/17.
 */
@Service
public class DeclaOperationRecordServiceImpl implements DeclaOperationRecordService {

    @Autowired
    private DeclarationFreeBiz declarationFreeBiz;
    @Autowired
    private DeclaCheckContentMapper declaCheckContentMapper;
    @Autowired
    private DeclaCheckCtDeptRefMapper declaCheckCtDeptRefMapper;
    @Autowired
    private DictionaryService dictionaryService;
    @Autowired
    private DeclaCheckTrackingMapper declaCheckTrackingMapper;
    @Autowired
    private DeclaOperationRecordMapper declaOperationRecordMapper;
    @Autowired
    private DeclarationMapper declarationMapper;
    @Autowired
    private DeclaDocHanOutRecordMapper declaDocHanOutRecordMapper;

    private Configuration configuration;
    @Autowired
    private UserBiz userBiz;


    /**
     * 保存支付提交 操作记录
     *
     * @param payId 付款订单ID
     */
    @Transactional
    public void savePaymentRecord(String payId) {
        //查询报关单费用
        List<DeclarationFree> declarationFrees = declarationFreeBiz.findFeeByPayId(payId);
        if (CollectionUtils.isNotEmpty(declarationFrees)) {
            String userId = LoginUtil.getLoginUserId();
            List<DeclaOperationRecord> recordList = new ArrayList<>();
            for (DeclarationFree fee : declarationFrees) {
                Declaration declaration = fee.getDeclaration();//获得报关单对象
                String did = declaration.getId();//报关单ID
                String businessNo = declaration.getBusinessId(); //业务编码
                DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.CUSTOMER_SUBMIT; //业务操作项目代码
                //组装操作记录对象
                DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, businessNo, opItem, "", userId);
                //准备保存
                recordList.add(record);
            }

            //保存操作记录
            declaOperationRecordMapper.batchInsert(recordList);
        }
    }

    /**
     * 保存客户申请驳回
     *
     * @param did 报关单ID
     */
    @Override
    @Transactional
    public void saveCustomerApplyRejectRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.CUSTOMER_APPLY_REJECT; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：供应商处理驳回申请
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSupplierAcceptRejectRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_ACCEPT_REJECT; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        ///保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：供应商海关退单
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSupplierChargeBackRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_CHARGE_BACK; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：供应商受理报关单
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSupplierDoValidRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_ACCEPT_SUBMIT; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：线下供应商受理报关单
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSecondSupplierDoValidRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_SEC_ACCEPT_SUBMIT; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：供应商驳回报关单
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSupplierDoRejectRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_REJECT_SUBMIT; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：上传报关单得到广版单一窗口
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSupplierDidGuangZhouSWUploadRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_GZ_SW_UPLOAD; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：上传报关单得到国版单一窗口
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSupplierCNSWUploadRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_CN_SW_UPLOAD; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：上传qp小工具
     *
     * @param did 报关单ID
     */
    @Override
    public void saveSupplierQPUploadRecord(String did) {
        String userId = LoginUtil.getLoginUserId(); //用户ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_QP_UPLOAD; //操作项目

        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    /**
     * 保存操作记录：供应商更新查验记录
     *
     * @param params 入参
     */
    @Override
    public void saveSupplierUpdateVerifyRecord(Map params) {
        String status = params.get("status").toString(); //查验状态
        String contentId = params.get("contentId").toString(); //查验内容ID
        DeclaOperationRecord.OperationEnum opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_CN_SW_UPLOAD; //操作项目
        //修改查验跟踪当前状态
        DeclaCheckContent dcc = declaCheckContentMapper.selectByPrimaryKey(contentId);
        switch (status) {
            case "0":
                opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_VERIFY_ING;
                break;
            case "1":
                opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_VERIFY_DONE;
                break;
            case "2":
                opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_VERIFY_FAIL;
                break;
            case "4":
                //区分放行单位
                String deptId = declaCheckCtDeptRefMapper.selectListByContentId(dcc.getId()).get(0).getItemId();
                Dictionary dt = dictionaryService.selectByPrimaryKey(deptId);
                if ("DEPT_COMMODITY".equals(dt.getDictionaryCode())) {
                    opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_VERIFY_SJ_PASS;
                } else if ("DEPT_CUSTOM".equals(dt.getDictionaryCode())) {
                    opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_VERIFY_CT_PASS;
                } else {
                    opItem = DeclaOperationRecord.OperationEnum.SUPPLIER_VERIFY_OT_PASS;
                }
                break;
        }
        DeclaCheckTracking tracking = declaCheckTrackingMapper.selectByPrimaryKey(dcc.getTrackingId());
        String did = tracking.getDid();
        String userId = LoginUtil.getLoginUserId(); //用户ID
        //封装为业务操作记录
        DeclaOperationRecord record = DeclaOperationRecord.newInstance(did, null, opItem, "", userId);
        //保存业务操作记录
        declaOperationRecordMapper.insert(record);
    }

    @Override
    public Page<Map> getGridData(Jqgrid jqgrid) {
        try {
            jqgrid.pageWithMybatis();
            jqgrid.sortWithMybatis();
            Map<String, Object> params = jqgrid.getFilterMap();
            //是否是供应商，用于区分显示和限制可操作内容
            boolean isSup = userBiz.currentUserContainOneOfRoles("供应商管理员", "报关公司");
            //是否是客户，用于区分显示和限制可操作内容
            boolean isCust = userBiz.currentUserContainOneOfRoles("客户");
            String curComId = LoginUtil.getLoginUser().getCompany().getId();
            if(isSup){
                params.put("supId", curComId);
            }
            if(isCust){
                params.put("custId", curComId);
            }
            List<Map> recordList = declaOperationRecordMapper.selectForGrid(params);
            return jqgrid.pageResult(recordList);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 报关单历史操作信息
     *
     * @param jqgrid 分页、排序、查询条件
     * @param did    报关单ID
     */
    public Page hisOpRecGridData(Jqgrid jqgrid, String did) {
        jqgrid.pageWithMybatis();
        jqgrid.sortWithMybatis();
        List<DeclaOperationRecordVO> recordList = declaOperationRecordMapper.selectVOByDid(did);
        return jqgrid.pageResult(recordList);
    }

    /**
     * 查看操作记录页面报关数据获取
     *
     * @param did 报关单ID
     */
    @Override
    public Map recDeclarationInfoFormData(String did) {
        return declarationMapper.selectForRecDeclarationForm(did);
    }

    /**
     * 保存人工产生的记录
     * 单证操作记录：待申领，申领中，已申领，已发放； 限制：只有拥有上一个状态的记录，才允许有下一个状态的记录
     * 线下操作记录：包括现场放行，其他，保存现场放行前，检查是否包申报记录。
     *
     * @param record 操作记录
     */
    @Transactional
    public Result saveRecord(DeclaOperationRecord record) {
        /*
         *逻辑： 1 入参检查
         *       2  前置条件检查
         *       3  保存
         */

        //step1 检查待保存数据是否可以使用
        String itCode = record.getRecItemCode();
        if (StringUtils.isEmpty(itCode) || !isvalidItemCode(itCode)) {
            return Result.newFailInstance("操作项无法识别");
        }
        String did = record.getDid();
        if (StringUtils.isEmpty(did)) {
            return Result.newFailInstance("保存失败：关联信息丢失");
        }

        //step2 检查前置条件
        if (DeclaOperationRecord.OperationEnum.SCENE_RELEASE.toString().equals(itCode)) {
            //必须已存在以下几项中的一项操作记录才能做现场放行。
            List<String> needExistsOneOfCodes = new ArrayList<>();
            needExistsOneOfCodes.add(DeclaOperationRecord.OperationEnum.SUPPLIER_CN_SW_UPLOAD.toString());
            needExistsOneOfCodes.add(DeclaOperationRecord.OperationEnum.SUPPLIER_GZ_SW_UPLOAD.toString());
            needExistsOneOfCodes.add(DeclaOperationRecord.OperationEnum.SUPPLIER_QP_UPLOAD.toString());
            if (declaOperationRecordMapper.countByDidAndCodes(did, needExistsOneOfCodes) == 0) {
                return Result.newFailInstance("请先将报关单上传到QP或单一窗口");
            }
            //联动操作 更新报关单状态为放行
            com.mrd.gtimpframe.entity.Declaration decla = new com.mrd.gtimpframe.entity.Declaration();
            decla.setId(record.getDid());
            decla.setState(
                    com.mrd.gtimpframe.entity.Declaration.DeclarationBusinessState.COMPLETE_STATE);
            declarationMapper.updateByPrimaryKeySelective(decla);
        } else if (DeclaOperationRecord.OperationEnum.DOC_WAIT.toString().equals(itCode) || DeclaOperationRecord.OperationEnum.DOC_RECEIVING.toString().equals(itCode) || DeclaOperationRecord.OperationEnum.DOC_RECEIVED.toString().equals(itCode) || DeclaOperationRecord.OperationEnum.DOC_SEND.toString().equals(itCode)) {
            //必须存在前一项操作记录才能保存下一项
            DeclaOperationRecord.OperationEnum[] itCodeArr = DeclaOperationRecord.OperationEnum.values();
            List<String> needExistsPrevCode = null;
            DeclaOperationRecord.OperationEnum prevOperation = null;
            DeclaOperationRecord.OperationEnum currOperation = null;
            for (int i = 0; i < itCodeArr.length; i++) {
                DeclaOperationRecord.OperationEnum oe = itCodeArr[i];
                if (oe.toString().equals(itCode)) {
                    prevOperation = itCodeArr[i - 1];
                    needExistsPrevCode = Collections.singletonList(prevOperation.toString());
                    currOperation = oe;
                    break;
                }
            }
            if (!DeclaOperationRecord.OperationEnum.DOC_WAIT.toString().equals(itCode) && needExistsPrevCode != null && declaOperationRecordMapper.countByDidAndCodes(did, needExistsPrevCode) == 0) {
                return Result.newFailInstance("请先完成【" + prevOperation.cnString() + "】操作登记");
            }
            //保存单证发放记录
            DeclaDocHanOutRecord docRecord = new DeclaDocHanOutRecord();
            docRecord.setId(StringUtils.getUUID());
            DeclaDocHanOutRecord.StatusEnum docStatus = DeclaDocHanOutRecord.StatusEnum.formOperationEnum(currOperation);
            docRecord.setStatus(docStatus.toString());
            docRecord.setStatusText(docStatus.cnString());
            docRecord.setCreateTime(new Date());
            docRecord.setDid(did);
            docRecord.setRemark(record.getRemark());
            docRecord.setCreator(LoginUtil.getLoginUserId());

            declaDocHanOutRecordMapper.insert(docRecord);
        }


        //step3 自动填充数据并保存
        record.setId(StringUtils.getUUID());
        record.setCreateTime(new Date());
        record.setCreator(LoginUtil.getLoginUserId());
        declaOperationRecordMapper.insert(record);

        return Result.newSuccessInstance("已保存");
    }

    /**
     * 下载单证发放记录
     */
    public void downloadDocHoRecord(HttpServletRequest request, HttpServletResponse response, Map<String, Object> params) throws Exception {
        List<Map<String, Object>> declaList = declarationMapper.selectRecDeclarationList(params);
        for (Map<String, Object> map : declaList) {
            Object bizStatus = map.get("recStatus");
            if (bizStatus != null) {
                String cnState = Declaration.DeclarationBusinessState.cnString(bizStatus.toString());
                map.put("recStatus", cnState);
            }
        }
        String directory = this.getClass().getResource("/").getPath() + File.separator + "templates" + File.separator + "doc";
        String fileName = "单证发放记录.xls";
        String ftlFileName = "download.ftl";
        Map<String, Object> varis = new HashMap<>();
        varis.put("declaList", declaList);
        // 中文文件名支持
        String encodedFileName;
        String agent = request.getHeader("USER-AGENT");
        if (agent != null && agent.contains("MSIE")) {// IE
            encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        } else if (agent != null && agent.contains("Mozilla")) {
            encodedFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
        } else {
            encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        }
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
        response.setHeader("Content-Length", "");
        process(directory, ftlFileName, varis, response.getOutputStream());
    }

    /**
     * 查询业务操作效率
     */
    @Override
    public void getOperationalEfficiency(Jqgrid jqgrid, HttpServletResponse response) {
        Company company = LoginUtil.getLoginUser().getCompany();
        if ("CC".equals(company.getType())) {
            jqgrid.addRule(new SearchRule("SUP_ID", SearchRuleOption.eq, company.getId()));
        }
        if ("CL".equals(company.getType())) {
            jqgrid.addRule(new SearchRule("CUSTOMER_COM_ID", SearchRuleOption.eq, company.getId()));
        }
        String whereCase = jqgrid.getWhereCase();
        jqgrid.pageWithMybatis();
        jqgrid.sortWithMybatis();
        List<OperationalEfficiency> operationalEfficiencies = declaOperationRecordMapper.getOperationalEfficiency(whereCase);
        PageInfo<OperationalEfficiency> pi = new PageInfo<>(operationalEfficiencies);
        JsonBinder jsonBinder = JsonBinder.buildNormalBinder();
        jsonBinder.setDateFormat("yyyy-MM-dd HH:mm:ss");
        ResponseUtils.renderJson(response, jsonBinder.toJson(new PageImpl(operationalEfficiencies, jqgrid.getPage(), pi.getTotal())));
    }

    /**
     * 业务操作效率记录下载
     */
    @Override
    public void downloadOperationalEfficiency(String whereCase, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Company company = LoginUtil.getLoginUser().getCompany();
        if ("CC".equals(company.getType())) {
            whereCase += "SUP_ID='" + company.getId() + "'";
        }
        if ("CL".equals(company.getType())) {
            whereCase += "CUSTOMER_COM_ID='" + company.getId() + "'";
        }
        List<OperationalEfficiency> operationalEfficiencies = declaOperationRecordMapper.getOperationalEfficiency(whereCase);
        String directory = this.getClass().getResource("/").getPath() + File.separator + "templates" + File.separator + "doc";
        Map<String, Object> varis = new HashMap<>();
        varis.put("operaList", operationalEfficiencies);
        String encodedFileName;
        String ftlFileName = "OperationalEfficiency.ftl";
        String fileName = "业务操作效率记录.xls";
        String agent = request.getHeader("USER-AGENT");
        if (agent != null && agent.contains("MSIE")) {// IE
            encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        } else if (agent != null && agent.contains("Mozilla")) {
            encodedFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
        } else {
            encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        }
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
        response.setHeader("Content-Length", "");
        process(directory, ftlFileName, varis, response.getOutputStream());
    }

    /**
     * 业务操作量统计
     */
    @Override
    public void getOperationStatistics(Jqgrid jqgrid, HttpServletResponse response) {
        Company company = LoginUtil.getLoginUser().getCompany();
        if ("CC".equals(company.getType())) {
            jqgrid.addRule(new SearchRule("SUP_ID", SearchRuleOption.eq, company.getId()));
        }
        if ("CL".equals(company.getType())) {
            jqgrid.addRule(new SearchRule("CUSTOMER_COM_ID", SearchRuleOption.eq, company.getId()));
        }
        String whereCase = jqgrid.getWhereCase();
        jqgrid.pageWithMybatis();
        jqgrid.sortWithMybatis();
        String declarationType = "全部";
        if (jqgrid != null && jqgrid.getFilters() != null && jqgrid.getFilters().getRules() != null) {
            for (SearchRule searchRule : jqgrid.getFilters().getRules()) {
                if ("DECLARATION_TYPE".equals(searchRule.getField())) {
                    declarationType = this.praseDeclarationType((String) searchRule.getData());
                }
            }
        }
        List<OperationStatistics> operationStatistics = declaOperationRecordMapper.getOperationStatistics(whereCase, declarationType);
        PageInfo<OperationStatistics> pi = new PageInfo<>(operationStatistics);
        JsonBinder jsonBinder = JsonBinder.buildNormalBinder();
        jsonBinder.setDateFormat("yyyy-MM-dd HH:mm:ss");
        ResponseUtils.renderJson(response, jsonBinder.toJson(new PageImpl(operationStatistics, jqgrid.getPage(), pi.getTotal())));
    }

    /**
     * 业务操作量统计记录下载
     */
    @Override
    public void downloadOperationStatistics(String declarationType, String whereCase, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (StringUtils.isEmpty(declarationType)) {
            declarationType = "全部";
        } else {
            declarationType = this.praseDeclarationType(declarationType);
        }
        Company company = LoginUtil.getLoginUser().getCompany();
        if ("CC".equals(company.getType())) {
            whereCase += "SUP_ID='" + company.getId() + "'";
        }
        if ("CL".equals(company.getType())) {
            whereCase += "CUSTOMER_COM_ID='" + company.getId() + "'";
        }
        List<OperationStatistics> operationStatistics = declaOperationRecordMapper.getOperationStatistics(whereCase, declarationType);
        String directory = this.getClass().getResource("/").getPath() + File.separator + "templates" + File.separator + "doc";
        Map<String, Object> varis = new HashMap<>();
        varis.put("statisticList", operationStatistics);
        String encodedFileName;
        String ftlFileName = "OperationStatistics.ftl";
        String fileName = "业务操作量统计记录.xls";
        String agent = request.getHeader("USER-AGENT");
        if (agent != null && agent.contains("MSIE")) {// IE
            encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        } else if (agent != null && agent.contains("Mozilla")) {
            encodedFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
        } else {
            encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        }
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
        response.setHeader("Content-Length", "");
        process(directory, ftlFileName, varis, response.getOutputStream());
    }

    /**
     * 查询报关单某一项操作项的登记数量
     * @param did 报关单ID
     * @param opItCode 操作项目
     */
    @Override
    public Integer countOperationRecord(String did, String opItCode) {
        try {
            if(isvalidItemCode(opItCode)){
                List<String> itCodes = Collections.singletonList(opItCode);
                return declaOperationRecordMapper.countByDidAndCodes(did, itCodes);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 是否是有效的操作代码
     *
     * @param itCode 操作项目代码
     */
    private boolean isvalidItemCode(String itCode) {
        DeclaOperationRecord.OperationEnum[] itCodeArr = DeclaOperationRecord.OperationEnum.values();
        for (DeclaOperationRecord.OperationEnum oe : itCodeArr) {
            if (oe.toString().equals(itCode)) {
                return true;
            }
        }
        return false;
    }

    private void initConfiguration(String fileDir) throws Exception {
        if (fileDir != null && !fileDir.trim().equals("")) {
            if (configuration == null) {
                configuration = new Configuration(Configuration.VERSION_2_3_23);
                configuration.setDefaultEncoding("UTF-8");
            } else {
                configuration.setTemplateLoader((TemplateLoader) null);
            }

            File directory = new File(fileDir);
            if (!directory.exists()) {
                throw new FileNotFoundException("没有找到模板文件目录!");
            } else {
                configuration.setTemplateLoader(new FileTemplateLoader(directory));
            }
        } else {
            throw new InvalidParameterException("传入了空的文件夹！请检查！！");
        }
    }

    private void process(String fileDir, String fileName, Map<String, Object> params, OutputStream out) throws Exception {
        if (fileName != null && !fileName.trim().equals("")) {
            File ftlModuleFile = new File(fileDir + File.separator + fileName);
            if (!ftlModuleFile.exists()) {
                throw new FileNotFoundException("没有找到模板文件!");
            } else {
                initConfiguration(fileDir);
                Template template = configuration.getTemplate(fileName);
                template.process(params, new OutputStreamWriter(out));
            }
        } else {
            throw new InvalidParameterException("文件名！请检查！！");
        }
    }

    private String praseDeclarationType(String declarationType) {
        switch (declarationType) {
            case "I"://各种因素导致数据库查询时以不等于I作为出口，不等于E作为进口
                declarationType = "出口";
                break;
            case "E":
                declarationType = "进口";
                break;
            default:
                declarationType = "全部";
        }
        return declarationType;
    }

}
